package cn.ad.server.job.adapter.persistence.job;

import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

import javax.annotation.Resource;

import cn.ad.server.job.adapter.dbaccess.DbDataContainer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Repository;

import cn.ad.server.job.adapter.dbaccess.AssembledCachedDataContainer;
import cn.ad.server.domain.ad.AdMaterial;
import cn.ad.server.domain.ad.AdSize;
import cn.ad.server.domain.ad.Creative;
import cn.ad.server.job.domain.job.AdMaterialWarmUpService;
import cn.ad.server.domain.enumration.AdFormat;
@Repository
public class AdMaterialWarmUpServant implements AdMaterialWarmUpService {
	
	private static Logger logger = LoggerFactory.getLogger(AdMaterialWarmUpServant.class);
	
	@Resource(name = "cacheRedisTemplate")
	private ValueOperations<String, AdMaterial> adMaterialsValueOperations;
	
	@Resource(name = "cacheRedisTemplate")
	private ValueOperations<String, Creative> creativeValueOperations;
	
	@Resource(name = "cacheRedisTemplate")
	private RedisTemplate<String, String> redisTemplate;
	
	@Resource(name = "cacheRedisTemplate")
	private HashOperations<String,Integer, AdMaterial> HstrategyOperations;
	
	@Autowired
	private AssembledCachedDataContainer container;

	public void cachedAdMaterial() {
		List<AdMaterial> mapAdms = DbDataContainer.getAdMaterialAll();//根据所有的数据
		if(mapAdms==null){
			return;
		}
		ConcurrentHashMap<Long, CopyOnWriteArraySet<AdMaterial>> mapper = container.getAdMaterialsByCreativeIdMap();
		ConcurrentHashMap<Long, AdMaterial> adMaterials = container.getAdMaterials();
		for (AdMaterial am:mapAdms) {
			try {
				mapper.putIfAbsent(am.getCreativeId(),new CopyOnWriteArraySet<AdMaterial>());
				if (am.getStatus() == 1) {
					am = attachAdSize(am);
					if (am!=null){
						mapper.get(am.getCreativeId()).add(am);
						adMaterials.put(am.getId(), am);
						upToRedis(am.getCreativeId(), am, true);
					}
				} else if (am.getStatus() != 1) {
					adMaterials.remove(Long.valueOf(am.getId()));
					mapper.get(am.getCreativeId()).remove(am);
					upToRedis(am.getCreativeId(), am, false);
				}
				
			} catch (Exception e) {
				if(am!=null){						
					logger.error("错误：在获取AdMaterial_id ="+am.getId()+"数据时发生错误 \n 错误信息：", e);
				}
			}
		}
	}
	
	
	public void warmUpAdMaterial() {
		cachedAdMaterial();
		List<Creative> creativeAll = DbDataContainer.getCreativeAll();
		ConcurrentHashMap<Long, CopyOnWriteArraySet<AdMaterial>> mapper = container.getAdMaterialsByCreativeIdMap();
		for (Creative creative : creativeAll) {
			if (creative.getStatus()==1) {
				if(creative.getAdFormat()!=AdFormat.AD_NATIVE){					
					creative.setAdMaterialSet(mapper.get(creative.getId()));
					creativeValueOperations.set(creative.toCacheKey(), creative);
				}
			}else{
				redisTemplate.delete(creative.toCacheKey());
			}
			
		}
		
		List<AdMaterial> mapAdms = DbDataContainer.getAdMaterialAll();//根据所有的数据
		for (AdMaterial am : mapAdms) {
			if (am.getStatus() == 1) {
				AdMaterial am2 = attachAdSize(am);
				if (am2!=null){
					adMaterialsValueOperations.set(am2.toCacheKey(), am2);
				}else{
					redisTemplate.delete(am.toCacheKey());
				}
			} else if (am.getStatus() != 1) {
				redisTemplate.delete(am.toCacheKey());
			}
		}
	}
	
	
	void upToRedis(Long cId,AdMaterial adm,boolean operatorFlg){
		if(!redisDebug){
			return;
		}
		String key = "AdMaterialsByCreativeId:"+cId+":"+adm.getId();
		if(operatorFlg){			
			adMaterialsValueOperations.set(key, adm);
			adMaterialsValueOperations.set(adm.toCacheKey(), adm);
		}else{
			redisTemplate.delete(key);
			redisTemplate.delete(adm.toCacheKey());
		}
	}
	
	/**
	 * 附上adsize
	 * @param adMaterial
	 * @return
    */
	private AdMaterial attachAdSize(AdMaterial adMaterial){
		if(adMaterial==null){
			return null;
		}
		//adSize
		AdSize adSize = adMaterial.getAdSize();
		if(adSize!=null){
			adSize = DbDataContainer.getAdSize(adMaterial.getAdSize().getId());
			adMaterial.setAdSize(adSize);
		}
		return adMaterial;
	}
	
	@Value("${cached.redisDebug:false}")
	private boolean redisDebug;

}
